package contower

import (
	"go.uber.org/zap"
	"sync"
	"time"
	"wzgames/internal/constant"
	"wzgames/internal/gloader"
	"wzgames/internal/gloader/election"
	"wzgames/pkg/actor/actor"
	"wzgames/pkg/actor/actorservice"
	"wzgames/pkg/common/timingwheel"
	"wzgames/pkg/logger"
)

// 选举master，然后进行各个实例播报

var (
	towerGuard *TowerGuard
	oncew      sync.Once
)

type TowerGuard struct {
	actorservice.ServiceMeta

	elect      *election.Election
	timerWheel *timingwheel.TimingWheel
}

func Actor() actorservice.IService {
	if towerGuard == nil {
		oncew.Do(func() {
			towerGuard = &TowerGuard{
				timerWheel: timingwheel.NewTimingWheel(time.Millisecond, 100),
			}
			towerGuard.Name = "actor_tower_guard"
			towerGuard.elect = election.NewElection(constant.CcAviatorElectPath, gloader.BootConfig().GetNodeID(), towerGuard.electionCallback)
		})
	}
	return towerGuard
}

func (tg *TowerGuard) OnReceive(ctx actor.Context) {
	switch ctx.Message().(type) {
	case StartElection:
		tg.doElection()
	default:
	}
}

func (tg *TowerGuard) OnStart(as *actorservice.ActorService) {
	tg.timerWheel.Start()
}

func (tg *TowerGuard) Attach(a interface{}) {

}

func (tg *TowerGuard) doElection() {
	err := tg.elect.Start(gloader.CClient())
	if err != nil {
		logger.Error("[ConTower] do election fail", zap.Error(err))
	}
}

// electionCallback Master开始启动实例播报管理
func (tg *TowerGuard) electionCallback(evt election.MasterEvent) {
	instMgr.StartInstants()
	logger.Info("[ConTower] aircraft control tower start", zap.String("NodeID", gloader.BootConfig().GetNodeID()))
}

func (tg *TowerGuard) OnDestroy() {
	tg.timerWheel.Stop()
	tg.elect.Stop()
	actorservice.Stop(tg.GetPID())
}

func TimerAfter(d time.Duration, fn func(interface{}), args interface{}) *timingwheel.Timer {
	return towerGuard.timerWheel.AfterFunc(d, fn, args)
}
